﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace MyKeyValueCollection
{
    public class MyKeyValuePairCollection : ICollection, IDisposable
    {
        #region Enumerator Class

        private class CollectionIterator : IEnumerator
        {
            public CollectionIterator(MyKeyValuePair[] array)
            {
                m_values = array;
            }

            #region IEnumerator Implementation

            public bool MoveNext()
            {
                m_position++;
                return (m_position < m_values.Length);
            }

            public void Reset()
            {
                m_position = -1;
            }

            object IEnumerator.Current
            {
                get
                {
                    try
                    {
                        return m_values[m_position];
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new IndexOutOfRangeException();
                    }
                }
            }


            #endregion

            #region Private Fields

            private MyKeyValuePair[] m_values;
            private int m_position = -1;

            #endregion
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Initialize new instance of MyKeyValuePairCollection
        /// </summary>
        /// <param name="values"></param>
        /// <param name="count">Amount of elements in collection</param>
        public MyKeyValuePairCollection(IEnumerable<MyKeyValuePair> values, int count)
        {
            
            m_Values = Array.CreateInstance(typeof(MyKeyValuePair), count) as MyKeyValuePair[];

            int index = -1;
            foreach (MyKeyValuePair item in values)
            {
                index++;
                m_Values.SetValue(item, index);
            }

            m_Count = index + 1;
        }

        #endregion

        #region Finalizer

        ~MyKeyValuePairCollection()
        {
            Dispose(false);
        }

        #endregion

        #region ICollection Implementation

        #region Properties

        public int Count
        {
            get { return m_Count; }
        }

        public bool IsSynchronized
        {
            get { return false; }
        }

        public object SyncRoot
        {
            get { return __mutex; }
        }

        #endregion

        /// <summary>
        /// Copies the elements of the m_Values to an System.Array, starting at a particular System.Array index.
        /// </summary>
        /// <param name="array">The one-dimensional System.Array that is the destination of the elements copied from m_Values. The System.Array must have zero-based indexing.</param>
        /// <param name="index">The zero-based index in array at which copying begins.</param>
        /// <exception cref="ArgumentNullException">array is null</exception>
        /// <exception cref="ArgumentOutOfRangeException">index is less than zero</exception>
        /// <exception cref="ArgumentException">array is multidimensional.-or- The number of elements in the source m_Values is greater than the available space from index to the end of the destination array.</exception>
        /// <exception cref="ArgumentException">the type of the source m_Values cannot be cast automatically to the type of the destination array</exception>
        public void CopyTo(Array array, int index)
        {
            if (array == null)
                throw new ArgumentNullException();

            if (index < 0)
                throw new ArgumentOutOfRangeException();

            if (m_Count > array.Length - index)
                throw new ArgumentException();

            if (array.GetType().GetElementType() != m_Values.GetType().GetElementType())
                throw new ArgumentException();

            for (int i = index; i < m_Count; i++)
            {
                array.SetValue(m_Values[i - index], i);
            }

        }

        /// <summary>
        /// Returns an enumerator that iterates through a collection.
        /// </summary>
        /// <returns>An IEnumerator object that can be used to iterate through the collection.</returns>
        public IEnumerator GetEnumerator()
        {
            return new CollectionIterator(this.m_Values);
        }

        #endregion

        #region IDisposable Implementation

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposeManaged)
        {
            if (m_IsDisposed)
                return;

            if (disposeManaged)
            {

                ///TODO: dispose managend resources
            }

            ///TODO: dispose unmanagend resources
            
            m_IsDisposed = true;
        }

        #endregion

        #region Private Fields

        private readonly object __mutex = new object();
        private readonly MyKeyValuePair[] m_Values;
        private readonly int m_Count;
        private bool m_IsDisposed = false;

        #endregion        
    }
}
